home *** CD-ROM | disk | FTP | other *** search
/ Language/OS - Multiplatform Resource Library / LANGUAGE OS.iso / gnu / emacs.lha / emacs-19.16 / src / alloca.s < prev    next >
Text File  |  1993-06-09  |  10KB  |  351 lines

  1. /* `alloca' standard 4.2 subroutine for 68000's and 16000's and others.
  2.    Also has _setjmp and _longjmp for pyramids.
  3.    Copyright (C) 1985, 1986, 1988 Free Software Foundation, Inc.
  4.  
  5. This file is part of GNU Emacs.
  6.  
  7. GNU Emacs is distributed in the hope that it will be useful,
  8. but WITHOUT ANY WARRANTY.  No author or distributor
  9. accepts responsibility to anyone for the consequences of using it
  10. or for whether it serves any particular purpose or works at all,
  11. unless he says so in writing.  Refer to the GNU Emacs General Public
  12. License for full details.
  13.  
  14. Everyone is granted permission to copy, modify and redistribute
  15. GNU Emacs, but only under the conditions described in the
  16. GNU Emacs General Public License.   A copy of this license is
  17. supposed to have been given to you along with GNU Emacs so you
  18. can know your rights and responsibilities.  It should be in a
  19. file named COPYING.  Among other things, the copyright notice
  20. and this notice must be preserved on all copies.  */
  21.  
  22.  
  23. /* Both 68000 systems I have run this on have had broken versions of alloca.
  24.    Also, I am told that non-berkeley systems do not have it at all.
  25.    So replace whatever system-provided alloca there may be
  26.    on all 68000 systems.  */
  27.  
  28. #define NOT_C_CODE
  29. #include "config.h"
  30.  
  31. #ifndef HAVE_ALLOCA  /* define this to use system's alloca */
  32.  
  33. #ifndef hp9000s300
  34. #ifndef m68k
  35. #ifndef m68000
  36. #ifndef WICAT
  37. #ifndef ns32000
  38. #ifndef ns16000
  39. #ifndef sequent
  40. #ifndef pyramid
  41. #ifndef ATT3B5
  42. #ifndef XENIX
  43. you
  44. lose!!
  45. #endif /* XENIX */
  46. #endif /* ATT3B5 */
  47. #endif /* pyramid */
  48. #endif /* sequent */
  49. #endif /* ns16000 */
  50. #endif /* ns32000 */
  51. #endif /* WICAT */
  52. #endif /* m68000 */
  53. #endif /* m68k */
  54. #endif /* hp9000s300 */
  55.  
  56.  
  57. #ifdef hp9000s300
  58. #ifdef OLD_HP_ASSEMBLER
  59.     data
  60.     text
  61.     globl    _alloca
  62. _alloca    
  63.     move.l    (sp)+,a0    ; pop return addr from top of stack
  64.     move.l    (sp)+,d0    ; pop size in bytes from top of stack
  65.     add.l    #ROUND,d0    ; round size up to long word
  66.     and.l    #MASK,d0    ; mask out lower two bits of size
  67.     sub.l    d0,sp        ; allocate by moving stack pointer
  68.     tst.b    PROBE(sp)    ; stack probe to allocate pages
  69.     move.l    sp,d0        ; return pointer
  70.     add.l    #-4,sp        ; new top of stack
  71.     jmp    (a0)        ; not a normal return
  72. MASK    equ    -4        ; Longword alignment
  73. ROUND    equ    3        ; ditto
  74. PROBE    equ    -128        ; safety buffer for C compiler scratch
  75.     data
  76. #else /* new hp assembler syntax */
  77. /*
  78.   The new compiler does "move.m <registers> (%sp)" to save registers,
  79.     so we must copy the saved registers when we mung the sp.
  80.   The old compiler did "move.m <register> <offset>(%a6)", which
  81.     gave us no trouble
  82.  */
  83.     text
  84.     set    PROBE,-128    # safety for C frame temporaries
  85.     set    MAXREG,22    # d2-d7, a2-a5, fp2-fp7 may have been saved
  86.     global    _alloca
  87. _alloca:
  88.     mov.l    (%sp)+,%a0    # return address
  89.     mov.l    (%sp)+,%d0    # number of bytes to allocate
  90.     mov.l    %sp,%a1        # save old sp for register copy
  91.     mov.l    %sp,%d1        # compute new sp
  92.     sub.l    %d0,%d1        # space requested
  93.     and.l    &-4,%d1        # round down to longword
  94.     sub.l    &MAXREG*4,%d1    # space for saving registers
  95.     mov.l    %d1,%sp        # save new value of sp
  96.     tst.b    PROBE(%sp)    # create pages (sigh)
  97.     mov.l    %a2,%d1        # save reg a2
  98.     mov.l    %sp,%a2
  99.     move.w    &MAXREG-1,%d0
  100. copy_regs_loop:            /* save caller's saved registers */
  101.     mov.l    (%a1)+,(%a2)+
  102.     dbra    %d0,copy_regs_loop
  103.     mov.l    %a2,%d0        # return value
  104.     mov.l    %d1,%a2        # restore a2
  105.     add.l    &-4,%sp        # adjust tos
  106.     jmp    (%a0)        # rts
  107. #endif /* new hp assembler */
  108. #else
  109. #ifdef m68k            /* SGS assembler totally different */
  110.     file    "alloca.s"
  111.     global    alloca
  112. alloca:
  113. #ifdef MOTOROLA_DELTA
  114. /* slightly modified version of alloca to motorola sysV/68 pcc - based
  115.    compiler. 
  116.    this compiler saves used registers relative to %sp instead of %fp.
  117.    alright, just make new copy of saved register set whenever we allocate
  118.    new space from stack..
  119.    this is true at last until SVR3V5.1 . bug has reported to Motorola. */
  120.     set    MAXREG,10    # max no of registers to save (d2-d7, a2-a5)
  121.         mov.l   (%sp)+,%a1    # pop return addr from top of stack
  122.         mov.l   (%sp)+,%d0    # pop size in bytes from top of stack
  123.     mov.l    %sp,%a0        # save stack pointer for register copy
  124.         addq.l  &3,%d0        # round size up to long word
  125.         andi.l  &-4,%d0        # mask out lower two bits of size
  126.     mov.l    %sp,%d1        # compute new value of sp to d1
  127.         sub.l    %d0,%d1        # pseudo-allocate by moving stack pointer
  128.     sub.l    &MAXREG*4,%d1    # allocate more space for saved regs.
  129.     mov.l    %d1,%sp        # actual allocation.
  130.     move.w    &MAXREG-1,%d0    # d0 counts saved regs.
  131.     mov.l    %a2,%d1        # preserve a2.
  132.     mov.l    %sp,%a2        # make pointer to new reg save area.
  133. copy_regs_loop:         # copy stuff from old save area.
  134.     mov.l    (%a0)+,(%a2)+    # save saved register
  135.     dbra    %d0,copy_regs_loop
  136.         mov.l   %a2,%a0        # now a2 is start of allocated space.
  137.     mov.l    %a2,%d0        # return it in both a0 and d0 to play safe.
  138.     mov.l    %d1,%a2        # restore a2.
  139.         subq.l  &4,%sp        # new top of stack
  140.         jmp     (%a1)        # far below normal return
  141. #else /* not MOTOROLA_DELTA */
  142.     mov.l    (%sp)+,%a1    # pop return addr from top of stack
  143.     mov.l    (%sp)+,%d0    # pop size in bytes from top of stack
  144.     add.l    &R%1,%d0    # round size up to long word
  145.     and.l    &-4,%d0        # mask out lower two bits of size
  146.     sub.l    %d0,%sp        # allocate by moving stack pointer
  147.     tst.b    P%1(%sp)    # stack probe to allocate pages
  148.     mov.l    %sp,%a0        # return pointer as pointer
  149.     mov.l    %sp,%d0        # return pointer as int to avoid disaster
  150.     add.l    &-4,%sp        # new top of stack
  151.     jmp    (%a1)        # not a normal return
  152.     set    S%1,64        # safety factor for C compiler scratch
  153.     set    R%1,3+S%1    # add to size for rounding
  154.     set    P%1,-132    # probe this far below current top of stack
  155. #endif /* not MOTOROLA_DELTA */
  156.  
  157. #else /* not m68k */
  158.  
  159. #ifdef m68000
  160.  
  161. #ifdef WICAT
  162. /*
  163.  * Registers are saved after the corresponding link so we have to explicitly
  164.  * move them to the top of the stack where they are expected to be.
  165.  * Since we do not know how many registers were saved in the calling function
  166.  * we must assume the maximum possible (d2-d7,a2-a5).  Hence, we end up
  167.  * wasting some space on the stack.
  168.  *
  169.  * The large probe (tst.b) attempts to make up for the fact that we have
  170.  * potentially used up the space that the caller probed for its own needs.
  171.  */
  172.     .procss m0
  173.     .config "68000 1"
  174.     .module    _alloca
  175. MAXREG:    .const    10
  176.     .sect    text
  177.     .global    _alloca
  178. _alloca:
  179.     move.l    (sp)+,a1    ; pop return address
  180.     move.l    (sp)+,d0    ; pop allocation size
  181.     move.l    sp,d1        ; get current SP value
  182.     sub.l    d0,d1        ; adjust to reflect required size...
  183.     sub.l    #MAXREG*4,d1    ; ...and space needed for registers
  184.     and.l    #-4,d1        ; backup to longword boundry
  185.     move.l    sp,a0        ; save old SP value for register copy
  186.     move.l    d1,sp        ; set the new SP value
  187.     tst.b    -4096(sp)    ; grab an extra page (to cover caller)
  188.     move.l    a2,d1        ; save callers register
  189.     move.l    sp,a2
  190.     move.w    #MAXREG-1,d0    ; # of longwords to copy
  191. loop:    move.l    (a0)+,(a2)+    ; copy registers...
  192.     dbra    d0,loop        ; ...til there are no more
  193.     move.l    a2,d0        ; end of register area is addr for new space
  194.     move.l    d1,a2        ; restore saved a2.
  195.     addq.l    #4,sp        ; caller will increment sp by 4 after return.
  196.     move.l    d0,a0        ; return value in both a0 and d0.
  197.     jmp    (a1)
  198.     .end    _alloca
  199. #else
  200.  
  201. /* Some systems want the _, some do not.  Win with both kinds.  */
  202. .globl    _alloca
  203. _alloca:
  204. .globl    alloca
  205. alloca:
  206.     movl    sp@+,a0
  207.     movl    a7,d0
  208.     subl    sp@,d0
  209.     andl    #~3,d0
  210.     movl    d0,sp
  211.     tstb    sp@(0)        /* Make stack pages exist  */
  212.                 /* Needed on certain systems
  213.                    that lack true demand paging */
  214.     addql    #4,d0
  215.     jmp    a0@
  216.  
  217. #endif /* not WICAT */
  218. #endif /* m68000 */
  219. #endif /* not m68k */
  220. #endif /* not hp9000s300 */
  221.  
  222. #if defined (ns16000) || defined (ns32000)
  223.  
  224.     .text
  225.     .align    2
  226. /* Some systems want the _, some do not.  Win with both kinds.  */
  227. .globl    _alloca
  228. _alloca:
  229. .globl    alloca
  230. alloca:
  231.  
  232. /* Two different assembler syntaxes are used for the same code
  233.     on different systems.  */
  234.  
  235. #ifdef sequent
  236. #define IM
  237. #define REGISTER(x) x
  238. #else
  239. #ifdef NS5   /* ns SysV assembler */
  240. #define IM $
  241. #define REGISTER(x) x
  242. #else
  243. #define IM $
  244. #define REGISTER(x) 0(x)
  245. #endif
  246. #endif
  247.  
  248. /*
  249.  * The ns16000 is a little more difficult, need to copy regs.
  250.  * Also the code assumes direct linkage call sequence (no mod table crap).
  251.  * We have to copy registers, and therefore waste 32 bytes.
  252.  *
  253.  * Stack layout:
  254.  * new    sp ->    junk    
  255.  *         registers (copy)
  256.  *    r0 ->    new data        
  257.  *         |       (orig retval)
  258.  *         |      (orig arg)
  259.  * old  sp ->    regs      (orig)
  260.  *        local data
  261.  *    fp ->    old fp
  262.  */
  263.  
  264.     movd    tos,r1        /*  pop return addr */
  265.     negd    tos,r0        /*  pop amount to allocate */
  266.     sprd    sp,r2
  267.     addd    r2,r0
  268.     bicb    IM/**/3,r0    /*  4-byte align */
  269.     lprd    sp,r0
  270.     adjspb    IM/**/36    /*  space for regs, +4 for caller to pop */
  271.     movmd    0(r2),4(sp),IM/**/4    /*  copy regs */
  272.     movmd    0x10(r2),0x14(sp),IM/**/4
  273.     jump    REGISTER(r1)    /* funky return */
  274. #endif /* ns16000 or ns32000 */
  275.  
  276. #ifdef pyramid
  277.  
  278. .globl _alloca
  279.  
  280. _alloca: addw $3,pr0    # add 3 (dec) to first argument
  281.     bicw $3,pr0    # then clear its last 2 bits
  282.     subw pr0,sp    # subtract from SP the val in PR0
  283.     andw $-32,sp    # keep sp aligned on multiple of 32.
  284.     movw sp,pr0    # ret. current SP
  285.     ret
  286.  
  287. #ifdef PYRAMID_OLD /* This isn't needed in system version 4.  */
  288. .globl __longjmp
  289. .globl _longjmp
  290. .globl __setjmp
  291. .globl _setjmp
  292.  
  293. __longjmp: jump _longjmp
  294. __setjmp:  jump _setjmp
  295. #endif
  296.  
  297. #endif /* pyramid */
  298.  
  299. #ifdef ATT3B5
  300.  
  301.     .align 4
  302.     .globl alloca
  303.  
  304. alloca:
  305.     movw %ap, %r8
  306.     subw2 $9*4, %r8
  307.     movw 0(%r8), %r1    /* pc */
  308.     movw 4(%r8), %fp
  309.     movw 8(%r8), %sp
  310.     addw2 %r0, %sp /* make room */
  311.     movw %sp, %r0 /* return value */
  312.     jmp (%r1) /* continue... */
  313.  
  314. #endif /* ATT3B5 */
  315.  
  316. #ifdef XENIX
  317.  
  318. .386
  319.  
  320. _TEXT segment dword use32 public 'CODE'
  321. assume   cs:_TEXT
  322.  
  323. ;-------------------------------------------------------------------------
  324.  
  325. public _alloca
  326. _alloca proc near
  327.  
  328.     pop    ecx        ; return address
  329.     pop    eax        ; amount to alloc
  330.     add    eax,3        ; round it to 32-bit boundary
  331.     and    al,11111100B    ;
  332.     mov    edx,esp        ; current sp in edx
  333.     sub    edx,eax        ; lower the stack
  334.     xchg    esp,edx        ; start of allocation in esp, old sp in edx
  335.     mov    eax,esp        ; return ptr to base in eax
  336.     push    [edx+8]        ; save poss. stored reg. values (esi,edi,ebx)
  337.     push    [edx+4]        ;  on lowered stack
  338.     push    [edx]        ;
  339.     sub    esp,4        ; allow for 'add esp, 4'
  340.     jmp    ecx        ; jump to return address
  341.  
  342. _alloca endp
  343.  
  344. _TEXT    ends
  345.  
  346. end
  347.  
  348. #endif /* XENIX */
  349.  
  350. #endif /* not HAVE_ALLOCA */
  351.